#include "iteradorub.h"

template<size_t D, size_t K>
IteradorUB<D, K>::IteradorUB(ArbolUB<D, K>& arbol, Point<D> min, Point<D> max) : arbol(arbol) {
    zMin = zCurve.map(min);
    zMax = zCurve.map(max);
    zCur = zMin;
}

template<size_t D, size_t K>
void IteradorUB<D, K>::start(std::function<void(Point<D>)> function) {
    recursive(arbol.raiz, zMax, function);
}

template<size_t D, size_t K>
void IteradorUB<D, K>::recursive(Node<ZPoint<D*K>, RegistroUB<D, K> >& nodo, ZPoint<D*K> nodeMax,
                                 std::function<void(Point<D>)> function) {

    for (auto it = nodo.getRecords().begin(); it != nodo.getRecords().end(); ++it) {
        if (zCur >= nodeMax)
            return;
        if (nodo.isLeave()) {
            RegistroUB<D, K> record = (*it).getData();
            zCur = record.getKey();
            if (zCurve.inRange(zMin, zMax, record.getKey()))
                function(record.getPoint());
        } else {
            ZPoint<D*K> key = (*it).getKey();
            if (key > zCur) {
                Node<ZPoint<D*K>, RegistroUB<D, K> > hijo = arbol.leerNodo((*it).getLeftNode());
                recursive(hijo, key < zMax ? key : zMax, function);
            }
        }
    }

    if (nodo.isLeave())
        zCur = zCurve.nextZAddress(zMin, zMax, ++zCur);
    else {
        if (zCur < nodeMax) {
            Node<ZPoint<D*K>, RegistroUB<D, K> > hijo = arbol.leerNodo(nodo.getRightNode());
            recursive(hijo, nodeMax, function);
        }
    }
}
